//-------------------------------------------------------------------------------------
// <copyright file="TransportDataItem.cs" company="Microsoft">
//      Copyright (c) 2003 Microsoft Corporation. All rights reserved.
//      THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
//      EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
//      WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// </copyright>
// <summary>
//      An item of transport data.
// </summary>  
//-------------------------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.BizTalk2004.Configuration
{
	#region Using directives

	using System;
	using System.Globalization;

	#endregion

	/// <summary>
	/// An item of transport data.
	/// </summary>
	internal class TransportDataItem
	{
		#region Member Variables

		private readonly string name;
		private readonly Type type;
		private readonly int typeCode;
		private object value;

		#endregion

		#region Constructors

		/// <summary>
		/// Creates a new transport data item from the type code with a specified value.
		/// </summary>
		/// <param name="name">
		/// The name of the item, which is case sensitive.
		/// </param>
		/// <param name="typeCode">
		/// The type code for the item. Note that this is not the integer value of the <see cref="System.TypeCode"/>
		/// enumeration, but is a BizTalk internal value.
		/// </param>
		/// <param name="value">
		/// The value of the item; this may be <b>null</b>.
		/// </param>
		public TransportDataItem(string name, int typeCode, object value)
			: this(name, TransportDataItem.GetTransportType(typeCode), value)
		{
		}

		/// <summary>
		/// Creates a new transport data item from the <see cref="System.Type"/> with a specified value.
		/// </summary>
		/// <param name="name">
		/// The name of the item, which is case sensitive.
		/// </param>
		/// <param name="type">
		/// The <see cref="System.Type"/> of the item.
		/// </param>
		/// <param name="value">
		/// The value of the item; this may be <b>null</b>.
		/// </param>
		public TransportDataItem(string name, Type type, object value)
		{
			//check inputs
			if (name == null || name.Length == 0)
			{
				throw new ArgumentNullException("name");
			}
			if (type == Type.Missing)
			{
				throw new ArgumentException("The type must be specified.", "type");
			}
			//save details
			this.name = name;
			this.type = type;
			this.typeCode = TransportDataItem.GetTransportTypeCode(type);
			this.value = value;
		}

		#endregion

		#region Properties

		/// <summary>
		/// Gets the name of the transport data item.
		/// </summary>
		/// <value>
		/// The name of the transport data item.
		/// </value>
		public string Name
		{
			get
			{
				return this.name;
			}
		}

		/// <summary>
		/// Gets the <see cref="System.Type"/> of the transport data item.
		/// </summary>
		/// <value>
		/// A <see cref="System.Type"/>.
		/// </value>
		public Type Type
		{
			get
			{
				return this.type;
			}
		}

		/// <summary>
		/// Gets the type code of the transport data item. Note that this is not the integer value of the 
		/// <see cref="System.TypeCode"/> enumeration, but is a BizTalk internal value.
		/// </summary>
		/// <value>
		/// An <see cref="System.Int32"/> type code.
		/// </value>
		public int TypeCode
		{
			get
			{
				return this.typeCode;
			}
		}

		/// <summary>
		/// Gets or sets the value of the transport data item.
		/// </summary>
		/// <value>
		/// The value of the transport data item; this may be <b>null</b>.
		/// </value>
		public object Value
		{
			get
			{
				return this.value;
			}
			set
			{
				this.value = value;
			}
		}

		/// <summary>
		/// Gets the value of the transport data item as a string that BizTalk will interpret correctly.
		/// </summary>
		/// <value>
		/// The value of the transport data item as a string that BizTalk will interpret correctly.
		/// </value>
		public virtual string ValueString
		{
			get
			{
				if (this.value == null)
				{
					return null;
				}
				else if (this.value.GetType() == typeof(bool))
				{
					return ((bool)this.value) ? "1" : "0";	//BizTalk uses 1 and 0 for booleans
				}
				else
				{
					return this.value.ToString();
				}
			}
		}

		#endregion

		#region Static Methods

		/// <summary>
		/// Gets the <see cref="System.Type"/> of an item given the type code.
		/// </summary>
		/// <param name="typeCode">
		/// The type code of the item.
		/// </param>
		/// <returns>
		/// The <see cref="System.Type"/> of the item.
		/// </returns>
		private static Type GetTransportType(int typeCode)
		{
			//TODO: Find out what the rest of these are!
			switch (typeCode)
			{
				case 3:
					return typeof(int);
				case 8:
					return typeof(string);
				case 11:
					return typeof(bool);
				case 19:
					return typeof(long);	
				default:
					throw new ArgumentException("This type of this type code is unknown.", "typeCode");
			}
		}

		/// <summary>
		/// Gets the type code of an item given the <see cref="System.Type"/>.
		/// </summary>
		/// <param name="type">
		/// The <see cref="System.Type"/> of the item.
		/// </param>
		/// <returns>
		/// The type code.
		/// </returns>
		private static int GetTransportTypeCode(Type type)
		{
			//TODO: Find out what the rest of these are!
			if (type == typeof(int))
			{
				return 3;
			}
			else if (type == typeof(string))
			{
				return 8;
			}
			else if (type == typeof(bool))
			{
				return 11;
			}
			else if (type == typeof(long))
			{
				return 19;
			}
			else
			{
				throw new ArgumentException("This type code of this type is unknown.", "type");
			}		
		}

		#endregion
	}
}

